package appcore

import (
	"dataconvertserver/server/configclass"
	"dataconvertserver/utils"
	"dataconvertserver/utils/ormdb"
	"encoding/json"
	"errors"
	"fmt"
	"strconv"
	"strings"

	"gitlab.upchinaproduct.com/taf/tafgo/taf/util/rogger"
)

func Init() {
	// Create a worker pool with 5 workers
	// Start the worker pool
	GetWorkerPoolInstance().Start()
}

// 生产者：从源数据库中读取数据并发送到通道
func HandleSourceDatabase(loggerObj *rogger.Logger, databaseId string, timestr string) (int, error) {
	var ret = 0
	var errorString error
	var configClass, _ = configclass.GetConfigManager().GetConfig(databaseId)
	var sourceStTemp = configClass.Source
	var sourceDb, _ = ormdb.GetSourceDb(databaseId)
	var dbQuantity = sourceStTemp.DbQuantity
	var tableQuantity = sourceStTemp.TableQuantity
	var pageSize, _ = strconv.Atoi(sourceStTemp.PageSize)
	for dbNumber := 0; dbNumber < dbQuantity; dbNumber++ {
		for tableNumber := 0; tableNumber < tableQuantity; tableNumber++ {
			var start = 0
			var offset = pageSize
			for {
				loggerObj.Debugf("{sourceStTemp.Sql}|%s", sourceStTemp.Sql)
				// 把配置结构体转json
				sourceStTemp.DbQuantity = dbNumber
				sourceStTemp.TableQuantity = tableNumber
				sourceStTemp.PageSize = strconv.Itoa(start) + "," + strconv.Itoa(offset)
				// 如果有指定的增量时间 修改自增时间并且不能修改原始confstruct的自增时间
				if len(strings.TrimSpace(timestr)) > 0 {
					sourceStTemp.IncrementDatetime = timestr
				}
				var sourceByte, err = json.Marshal(&sourceStTemp)
				if err != nil {
					ret = -2
					errorString = fmt.Errorf("warning sourceSt Marshal %+v", err)
					continue
				}
				var sourceStMap map[string]interface{}
				err = json.Unmarshal(sourceByte, &sourceStMap)
				if err != nil {
					ret = -3
					errorString = fmt.Errorf("warning sourceSt Unmarshal %+v", err)
					continue
				}
				formatSourceSqlString, err := FindPairAndReplace(loggerObj, sourceStTemp.Sql, sourceStMap)
				if err != nil {
					ret = -4
					loggerObj.Debugf("{warning formatSourceSqlString.Sql}|%+v|%s|%+v", err, sourceStTemp.Sql, sourceStMap)
					errorString = fmt.Errorf("warning formatSourceSqlString.Sql %+v|%s|%+v", err, sourceStTemp.Sql, sourceStMap)
					continue
				}
				loggerObj.Debugf("{formatSourceSqlString.Sql}|%+v", formatSourceSqlString)
				var dcacheKVListTemp []map[string]interface{}
				sourceDb.Raw(formatSourceSqlString).Scan(&dcacheKVListTemp)
				// 将数据发送到通道
				for index, entry := range dcacheKVListTemp {
					task := Task{Id: index, DatabaseID: databaseId, DataBaseKV: entry}
					GetWorkerPoolInstance().AddTask(task)
				}
				// 如果查询数量不满一整页 查询数量为空 就是到尾页了 还能避免pageSize为0的情况
				if len(dcacheKVListTemp) < pageSize || len(dcacheKVListTemp) <= 0 {
					break
				} else {
					start = offset
					offset = offset + pageSize
				}
			}
		}
	}
	return ret, errorString
}

// 消费者：从通道读取数据并插入到目标数据库
func HandleDestinationDatabases(loggerObj *rogger.Logger, task Task) (int, error) {
	// 示例处理逻辑，可以根据实际需要添加更多处理步骤
	loggerObj.Debugf("Processing task %d for DatabaseID %s and DataBaseKV %+v", task.Id, task.DatabaseID, task.DataBaseKV)
	var ret = 0
	var errorString error
	DatabaseIdConfig, exists := configclass.GetConfigManager().GetConfig(task.DatabaseID)
	if !exists {
		loggerObj.Debugf("{warning DatabaseID not exists}|%s", task.DatabaseID)
		ret = -2
		errorString = fmt.Errorf("{warning DatabaseID not exists}|%s", task.DatabaseID)
		return ret, errorString
	}
	sourceDb, _ := ormdb.GetSourceDb(task.DatabaseID)
	destinationDb, _ := ormdb.GetDestinationDb(task.DatabaseID)
	if sourceDb == nil || destinationDb == nil {
		loggerObj.Errorf("{error task.DatabaseID}|%s", task.DatabaseID)
		ret = -3
		errorString = fmt.Errorf("{error task.DatabaseID}|%s", task.DatabaseID)
		return ret, errorString
	}
	var destinationSql = DatabaseIdConfig.Destination.Sql
	//把json中的值替换到sql语句中
	// loggerObj.Debugf("{destinationSql}|%s", destinationSql)
	var formatDestinationSqlString, err = FindPairAndReplace(loggerObj, destinationSql, task.DataBaseKV)
	if err != nil {
		loggerObj.Debugf("{error formatDestinationSqlString}|%+v|%s", err, destinationSql)
		ret = -4
		errorString = fmt.Errorf("error formatDestinationSqlString|%+v|%s", err, destinationSql)
		return ret, errorString
	}
	loggerObj.Debugf("{formatDestinationSqlString}|%s", formatDestinationSqlString)
	result := destinationDb.Exec(formatDestinationSqlString)
	if result.Error != nil {
		loggerObj.Debugf("{failed to execute SQL statement}|%+v|%s", result.Error, formatDestinationSqlString)
		ret = -5
		errorString = fmt.Errorf("failed to execute SQL statement|%+v|%s", result.Error, formatDestinationSqlString)
	} else {
		// 处理完成比较日期大小更新增量日期
		//t1 := utils.UnixSecondToTime(task.DataBaseKV["auto_updatetime"].(int64))
		t1, err := utils.InterfaceToTime(task.DataBaseKV["auto_updatetime"])
		if err != nil {
			loggerObj.Debugf("{warning auto_updatetime to time.Time failed}|%+v|%+v", err, task.DataBaseKV)
			ret = -6
			errorString = fmt.Errorf("{warning auto_updatetime to time.Time failed}|%+v|%+v", err, task.DataBaseKV)
			return ret, errorString
		}
		var originTime, _ = configclass.GetConfigManager().GetIncrementDatetime(task.DatabaseID)
		var t2 = utils.TimeStrToTimeDefault(originTime)
		// 将时间转换为字符串
		var taskTimeStr = utils.TimeToDefaultStr(t1)
		var configTimeStr = utils.TimeToDefaultStr(t2)
		// 将三个字符串连接成一个变量
		timeLogStr := fmt.Sprintf("taskTime:%s|configTime:%s", taskTimeStr, configTimeStr)
		//loggerObj.Debugf("{[increment_datetime] taskTime^configTime^updateConfigTime}|%s", timeLogStr)
		if t1.After(t2) {
			configclass.GetConfigManager().SetIncrementDatetime(task.DatabaseID, utils.TimeToDefaultStr(t1))
			loggerObj.Debugf("{increment_datetime has updated}|%s", timeLogStr)
		}
		loggerObj.Debugf("{executeSqlSuccessfully result}|%s|%+v", timeLogStr, result)
	}
	return ret, errorString
}

// 查找${}一对括号符号
func FindPairAndReplace(loggerObj *rogger.Logger, srcString string, recordMap map[string]interface{}) (string, error) {
	var ret = 0
	var errorString error
	var destString = srcString
	for {
		// 查找这个符号的开始和结束 ${}
		startIndex := strings.Index(destString, "${")
		if startIndex == -1 {
			// 已经替换完成 找不到${符号了 可以结束了
			break
		}
		endIndex := strings.Index(destString[startIndex:], "}") + startIndex
		if endIndex == -1 {
			// 找不到}符号 匹配不了${
			ret = -3
			errorString = fmt.Errorf("destString } Not Found")
			break
		}

		// 提取括号内的变量名
		variableName := destString[startIndex+2 : endIndex]

		// 提取json表达式和最终转换的类型
		variableSplit := strings.Split(variableName, "|")
		if len(variableSplit) < 2 {
			loggerObj.Debugf("{variableSplit length < 2}|%+v", variableSplit)
			ret = -4
			errorString = fmt.Errorf("variableSplit length < 2 %+v", variableSplit)
			break
		}
		jsonKeyExpress := variableSplit[0]
		jsonConvertType := variableSplit[1]

		// 用变量名取json中的值
		jsonObjValue, err := GetJsonValue(recordMap, strings.Split(jsonKeyExpress, "."))
		if err != nil {
			loggerObj.Debugf("{user field not found or not a string}|%+v", err)
			ret = -5
			errorString = fmt.Errorf("user field not found or not a string: %+v", err)
			break
		}
		jsonObjValueResult := JsonObjValue2ValueVarchar(jsonObjValue, jsonConvertType)
		destString = destString[:startIndex] + jsonObjValueResult + destString[endIndex+1:]
	}
	if ret == 0 {
		return destString, nil
	} else {
		return "", errorString
	}
}

// 传入任意数据类型和要转换的database数据类型
func JsonObjValue2ValueVarchar(jsonObjValue interface{}, jsonConvertType string) string {
	// 把取出的值转换为具体的类型
	jsonObjValueResult := Val2Str(jsonObjValue)
	if jsonObjValueResult != "" {
		if jsonConvertType == "string" || jsonConvertType == "varchar" {
			// 先把字符本身的单引号转义
			jsonObjValueResult = strings.ReplaceAll(jsonObjValueResult, "'", "\\'")
			// string需要加引号
			jsonObjValueResult = "'" + jsonObjValueResult + "'"
		} else if jsonConvertType == "int" {
			// int不用加引号
		} else if jsonConvertType == "timestamp" {
			// timestamp
			if jsonObjValueResult <= "0" {
				jsonObjValueResult = "null"
			} else {
				jsonObjValueResult = "from_unixtime(" + jsonObjValueResult + ")"
			}
		} else if jsonConvertType == "date" || jsonConvertType == "datetime" {
			// date需要加引号
			jsonObjValueResult = "'" + jsonObjValueResult + "'"
		} else if jsonConvertType == "any" || jsonConvertType == "unknown" {
			// 不用加引号 避免empty branch警告
			_ = 0
		}
	} else {
		jsonObjValueResult = "null"
	}
	return jsonObjValueResult
}

// Val2Str 转换成字符串
func Val2Str(value interface{}) string {
	var str string
	if value == nil {
		return str
	}
	// switch value.(type) {
	switch vt := value.(type) {
	case float64:
		str = strconv.FormatFloat(vt, 'f', -1, 64)
	case float32:
		str = strconv.FormatFloat(float64(vt), 'f', -1, 64)
	case int:
		str = strconv.Itoa(vt)
	case uint:
		str = strconv.Itoa(int(vt))
	case int8:
		str = strconv.Itoa(int(vt))
	case uint8:
		str = strconv.Itoa(int(vt))
	case int16:
		str = strconv.Itoa(int(vt))
	case uint16:
		str = strconv.Itoa(int(vt))
	case int32:
		str = strconv.Itoa(int(vt))
	case uint32:
		str = strconv.Itoa(int(vt))
	case int64:
		str = strconv.FormatInt(vt, 10)
	case uint64:
		str = strconv.FormatUint(vt, 10)
	case string:
		str = value.(string)
	case []byte:
		str = string(vt)
	default:
		newValue, _ := json.Marshal(value)
		str = string(newValue)
	}

	return str
}

func isArray(value interface{}) bool {
	_, ok := value.([]interface{})
	return ok
}

func isObject(value interface{}) bool {
	_, ok := value.(map[string]interface{})
	return ok
}

func isPrimitive(value interface{}) bool {
	switch value.(type) {
	case string, bool, float64, int:
		return true
	default:
		return false
	}
}

// 传入json, json表达式|是否需要parse，返回json表达式对应的值
func GetJsonValue(jsonData map[string]interface{}, keys []string) (interface{}, error) {
	var jsonMap interface{}
	jsonMap = jsonData

	for _, key := range keys {
		tokens := strings.Split(key, ":")
		//fmt.Printf("split key: %s\n", tokens)
		var firstKey string
		var secondKey string
		if len(tokens) > 1 {
			firstKey = tokens[0]
			secondKey = tokens[1]
		} else if len(tokens) > 0 {
			firstKey = tokens[0]
		} else {
			return nil, errors.New("empty split key")
		}
		//fmt.Printf("firstKey: %s, secondKey: %s\n", firstKey, secondKey)

		if firstKey == "" {
			return nil, errors.New("empty key")
		}

		switch {
		case secondKey == "parse":
			jsonString, ok := jsonMap.(map[string]interface{})
			if !ok {
				return nil, errors.New("expected string type for parsing JSON")
			}
			//fmt.Println("json string:", jsonString)
			var parsedJSON interface{}
			if err := json.Unmarshal([]byte(jsonString[firstKey].(string)), &parsedJSON); err != nil {
				return nil, fmt.Errorf("JSON parse error: %+v", err)
			}
			jsonMap = parsedJSON
		case jsonMap == nil:
			return nil, errors.New("empty json object")
		case isArray(jsonMap):
			index, err := strconv.Atoi(firstKey)
			if err != nil {
				return nil, fmt.Errorf("invalid array index: %+v", err)
			}
			array, ok := jsonMap.([]interface{})
			if !ok {
				return nil, errors.New("expected array type")
			}
			if index < 0 || index >= len(array) {
				return nil, errors.New("array index out of range")
			}
			jsonMap = array[index]
		case isObject(jsonMap):
			object, ok := jsonMap.(map[string]interface{})
			if !ok {
				return nil, errors.New("expected object type")
			}
			jsonMap = object[firstKey]
		case isPrimitive(jsonMap):
			return jsonMap, nil
		default:
			return nil, errors.New("invalid JSON structure")
		}
	}

	return jsonMap, nil
}

// 测试json表达式
func Test() {

	jsonStr := "{\"code\":200,\"msg\":\"hello\",\"data\":{\"uid\":\"User_1001\",\"info\":{\"sex\":\"0\",\"tel\":\"18800001001\"},\"hobby\":[\"aa\",\"bb\",\"cc\"]}}"
	var data map[string]interface{}
	if err := json.Unmarshal([]byte(jsonStr), &data); err != nil {
		fmt.Printf("json.Unmarshal jsonStr failed, err:%+v\n", err)
		return
	}
	fmt.Println("User:", data)

	stingTemp, err := GetJsonValue(data, strings.Split("data.info.tel", "."))
	if err != nil {
		fmt.Println("user field not found or not a string ", err)
		return
	}
	string1 := stingTemp.(string)
	fmt.Println("string1:", string1)

	jsonStr2 := `{
            "lastLogoutTime": -1,
            "serviceBranchId": "",
            "serviceBranch": "重庆分公司",
            "liveBodyRejReason": "",
            "authZStatus": 1,
            "userExtendInfo": "{\"rejectedReason\":\"\",\"step\":0,\"updateTime\":0,\"actionLog\":[],\"resultStr\":\"{\\\"area\\\":\\\"河北省\\/遵化市\\/东新庄镇前稻地村三小区\\\",\\\"address\\\":\\\"河北省遵化市东新庄镇前稻地村三小区208号\\\",\\\"postcode\\\":\\\"8896\\\",\\\"workunit\\\":\\\"zm\\\",\\\"income\\\":\\\"6666\\\",\\\"depart\\\":\\\"重庆分公司\\\",\\\"sameAddress\\\":true,\\\"selfControl\\\":true,\\\"selfBenefit\\\":false,\\\"integrityGood\\\":false,\\\"chineseTax\\\":true,\\\"departId\\\":\\\"1901\\\",\\\"educationKey\\\":10,\\\"education\\\":\\\"中专\\\",\\\"jobKey\\\":15,\\\"job\\\":\\\"普通职工\\\",\\\"jobPositionKey\\\":24,\\\"jobPosition\\\":\\\"信息运输、软件和信息技术服务人员\\\"}\",\"validDay\":-1,\"finishTime\":1682410714,\"status\":1,\"uid\":\"\"}",
            "authStep": 1,
            "openInfo": "{\"vOpenInfo\":[{\"sId\":\"\",\"sUionID\":\"\",\"sOpenID\":\"\",\"plat\":1}]}",
            "lastLoginTime": 1712806332,
            "mobileEnc": "",
            "headUrl": "https://dev.shgsec.com:16034/group0/M00/00/26/CjygMWOismiAYLjCAAAhBnCdnE40505137",
            "liveBodyCAInfo": "{\"rejectedReason\":\"\",\"step\":0,\"updateTime\":0,\"actionLog\":[],\"resultStr\":\"{\\\"sPortrait\\\":\\\"https:\\\\\\/\\\\\\/dev.shgsec.com:16034\\\\\\/group0\\\\\\/M00\\\\\\/00\\\\\\/2A\\\\\\/CjygMWQ3mz-AUu9OAAH4k109dyo1035852\\\",\\\"sFaceCompare\\\":\\\"97\\\"}\",\"validDay\":-1,\"finishTime\":1682410714,\"status\":1,\"uid\":\"sg_2bf2eaef58d9\"}",
            "regMN": "sdk",
            "regTime": 1657503963,
            "regMO": "Pixel 3",
            "reskTestCAInfo": "{\"rejectedReason\":\"\",\"step\":0,\"updateTime\":0,\"actionLog\":[],\"resultStr\":\"{\\\"score\\\":62,\\\"riskLevel\\\":\\\"积极型\\\",\\\"investDuring\\\":\\\"无特别要求\\\",\\\"investKinds\\\":\\\"股票、混合型基金、偏股型基金、股票型基金等权益类投资品种\\\",\\\"protocolUrl\\\":\\\"https:\\/\\/dev.shgsec.com:16034\\/group0\\/M00\\/00\\/2A\\/CjygMWQ-PK6Af7DVAAJNvVwWl_c554.pdf\\\",\\\"quesPdfUrl\\\":\\\"https:\\/\\/dev.shgsec.com:16034\\/group0\\/M00\\/00\\/2A\\/CjygMWQ-PK6AWAEhAAPD7_1HuJs848.pdf\\\"}\",\"validDay\":365,\"finishTime\":1681800346,\"status\":-3,\"uid\":\"\"}",
            "ch": "1234",
            "userAddressInfo": "",
            "sex": 0,
            "nickname": "188****1002",
            "sign": "6666666666",
            "status": 1,
            "updateTime": 1712806626,
            "password": "9f94ab1e5052958404c04f657b0b1452",
            "mobilePrx": "+86",
            "stopTime": -1,
            "uid": "sg_2bf2eaef58d9",
            "identNum": "",
            "deleteTime": -1,
            "clientId": "1002000008",
            "mobile": "18800001002",
            "fundsIds": "81002000008",
            "identCAInfo": "{\"rejectedReason\":\"\",\"step\":0,\"updateTime\":0,\"actionLog\":[],\"resultStr\":\"{\\\"address\\\":\\\"河北省遵化市东新庄镇前稻地村三小区208号\\\",\\\"birth\\\":\\\"1999\\/4\\/12\\\",\\\"id\\\":\\\"fedeefcea04a5b5f6de1a7c4a4df18b8ae6bc48313610b5fe0da679c169231be\\\",\\\"name\\\":\\\"李佳兴\\\",\\\"nation\\\":\\\"汉\\\",\\\"sex\\\":\\\"男\\\",\\\"frontSUrl\\\":\\\"https:\\/\\/dev.shgsec.com:16034\\/group0\\/M00\\/00\\/2D\\/CjygMWRGOVOALfzAAAKgnl_jC8M45.jpeg\\\",\\\"sPortrait\\\":\\\"https:\\/\\/dev.shgsec.com:16034\\/group0\\/M00\\/00\\/2D\\/CjygMWRGOVOAKVufAADK4937SLY44.jpeg\\\",\\\"authority\\\":\\\"遵化市公安局\\\",\\\"card_type\\\":\\\"1\\\",\\\"valid_date\\\":\\\"2019.02.20-2029.02.20\\\",\\\"backSUrl\\\":\\\"https:\\/\\/dev.shgsec.com:16034\\/group0\\/M00\\/00\\/2D\\/CjygMWRGOViAQvY9AAMKoozQDfE58.jpeg\\\",\\\"ID\\\":\\\"fedeefcea04a5b5f6de1a7c4a4df18b8ae6bc48313610b5fe0da679c169231be\\\"}\",\"validDay\":-1,\"finishTime\":1682410714,\"status\":1,\"uid\":\"\"}",
            "realName": "李佳兴"
        }`
	var data2 map[string]interface{}
	if err := json.Unmarshal([]byte(jsonStr2), &data2); err != nil {
		fmt.Printf("json.Unmarshal jsonStr2 failed, err:%+v\n", err)
		return
	}
	fmt.Println("User:", data2)
	value2, err := GetJsonValue(data2, strings.Split("identCAInfo:parse.resultStr:parse.address", "."))
	if err != nil {
		fmt.Println("user field not found or not a string ", err)
		return
	}
	fmt.Println("value2:", value2)

	var jsonData map[string]interface{}
	jsonString := "{\"rejectedReason\":\"jinitaimei\",\"resultStr\":\"{\\\"birth\\\":\\\"1999\\/4\\/12\\\",\\\"ID\\\":\\\"fedeefcea04a5b5f6de1a7c4a4df18b8ae6bc48313610b5fe0da679c169231be\\\",\\\"frontSUrl\\\":\\\"https:\\/\\/dev.shgsec.com:16034\\/group0\\/M00\\/00\\/2D\\/CjygMWRGOVOALfzAAAKgnl_jC8M45.jpeg\\\"}\",\"validDay\":-1}"
	if err := json.Unmarshal([]byte(jsonString), &jsonData); err != nil {
		fmt.Printf("json.Unmarshal jsonString failed, err:%+v\n", err)
		return
	}
	fmt.Println("jsonString2:", jsonData)
	fmt.Println("jsonString3:", jsonData["resultStr"])

	// 解析 resultStr 的值为内部的 map[string]interface{}
	var resultData map[string]interface{}
	err = json.Unmarshal([]byte(jsonData["resultStr"].(string)), &resultData)
	if err != nil {
		fmt.Println("resultStr 解析失败:", err)
		return
	}

	// 获取 birth 的值
	birth := resultData["birth"].(string)

	// 输出 birth 的值
	fmt.Println("birth:", birth)
}
